#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
8888端口连接诊断工具
用于分析和解决目标服务器连接问题
"""

import socket
import time
import threading
import subprocess
import sys
import json
from datetime import datetime
import traceback

# 导入安全属性访问器
try:
    from core.safe_attribute_accessor import safe_getattr, safe_hasattr
except ImportError:
    # 如果导入失败，提供简单的备用实现
    def safe_getattr(obj, attr, default=None):
        return getattr(obj, attr, default)
    
    def safe_hasattr(obj, attr):
        return hasattr(obj, attr)

class ConnectionDiagnostics:
    """连接诊断工具"""
    
    def __init__(self, target_ip="192.168.10.129", target_port=8888):
        self.target_ip = target_ip
        self.target_port = target_port
        self.results = {
            "timestamp": datetime.now().isoformat(),
            "target": f"{target_ip}:{target_port}",
            "tests": []
        }
    
    def log_result(self, test_name, success, details, error=None):
        """记录测试结果"""
        result = {
            "test_name": test_name,
            "success": success,
            "timestamp": datetime.now().isoformat(),
            "details": details
        }
        if error:
            result["error"] = str(error)
        
        self.results["tests"].append(result)
        
        status = "✅ 成功" if success else "❌ 失败"
        print(f"[{datetime.now().strftime('%H:%M:%S')}] {test_name}: {status}")
        if details:
            for key, value in details.items():
                print(f"  - {key}: {value}")
        if error:
            print(f"  - 错误: {error}")
        print()
    
    def test_basic_connectivity(self):
        """测试基础连通性"""
        print("🔍 测试基础连通性...")
        
        # Ping测试
        try:
            result = subprocess.run(
                ["ping", "-n", "4", self.target_ip],
                capture_output=True, text=True, timeout=10
            )
            ping_success = result.returncode == 0
            
            self.log_result("Ping测试", ping_success, {
                "返回码": result.returncode,
                "输出": result.stdout[:200] + "..." if len(result.stdout) > 200 else result.stdout
            })
        except Exception as e:
            self.log_result("Ping测试", False, {}, e)
    
    def test_port_accessibility(self):
        """测试端口可访问性"""
        print("🔍 测试端口可访问性...")
        
        try:
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            sock.settimeout(5)
            
            start_time = time.time()
            result = sock.connect_ex((self.target_ip, self.target_port))
            end_time = time.time()
            
            sock.close()
            
            success = result == 0
            connection_time = (end_time - start_time) * 1000
            
            self.log_result("端口连接测试", success, {
                "连接时间": f"{connection_time:.2f}ms",
                "错误码": result
            })
            
        except Exception as e:
            self.log_result("端口连接测试", False, {}, e)
    
    def test_multiple_connections(self, count=10):
        """测试多次连接的稳定性"""
        print(f"🔍 测试连接稳定性 ({count}次连接)...")
        
        successful_connections = 0
        connection_times = []
        errors = []
        
        for i in range(count):
            try:
                sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                sock.settimeout(3)
                
                start_time = time.time()
                result = sock.connect_ex((self.target_ip, self.target_port))
                end_time = time.time()
                
                if result == 0:
                    successful_connections += 1
                    connection_times.append((end_time - start_time) * 1000)
                else:
                    errors.append(f"连接{i+1}: 错误码{result}")
                
                sock.close()
                time.sleep(0.5)  # 避免过于频繁的连接
                
            except Exception as e:
                errors.append(f"连接{i+1}: {str(e)}")
        
        success_rate = (successful_connections / count) * 100
        avg_time = sum(connection_times) / len(connection_times) if connection_times else 0
        
        self.log_result("连接稳定性测试", success_rate > 50, {
            "成功连接": f"{successful_connections}/{count}",
            "成功率": f"{success_rate:.1f}%",
            "平均连接时间": f"{avg_time:.2f}ms",
            "最快连接": f"{min(connection_times):.2f}ms" if connection_times else "N/A",
            "最慢连接": f"{max(connection_times):.2f}ms" if connection_times else "N/A",
            "错误数量": len(errors)
        })
        
        if errors and len(errors) <= 5:  # 只显示前5个错误
            for error in errors[:5]:
                print(f"    {error}")
    
    def test_service_response(self):
        """测试服务响应"""
        print("🔍 测试服务响应...")
        
        try:
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            sock.settimeout(5)
            
            # 连接到目标
            result = sock.connect_ex((self.target_ip, self.target_port))
            
            if result == 0:
                # 尝试发送测试数据
                test_data = b"whoami\n"
                sock.send(test_data)
                
                # 等待响应
                sock.settimeout(3)
                response = sock.recv(1024)
                
                self.log_result("服务响应测试", True, {
                    "发送数据": test_data.decode().strip(),
                    "响应长度": len(response),
                    "响应内容": response.decode('utf-8', errors='ignore')[:100]
                })
                
            else:
                self.log_result("服务响应测试", False, {
                    "连接失败": f"错误码 {result}"
                })
            
            sock.close()
            
        except Exception as e:
            self.log_result("服务响应测试", False, {}, e)
    
    def test_concurrent_connections(self, concurrent_count=5):
        """测试并发连接"""
        print(f"🔍 测试并发连接 ({concurrent_count}个并发)...")
        
        results = []
        threads = []
        
        def connect_test(thread_id):
            try:
                sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                sock.settimeout(5)
                
                start_time = time.time()
                result = sock.connect_ex((self.target_ip, self.target_port))
                end_time = time.time()
                
                results.append({
                    "thread_id": thread_id,
                    "success": result == 0,
                    "time": (end_time - start_time) * 1000,
                    "error_code": result
                })
                
                sock.close()
                
            except Exception as e:
                results.append({
                    "thread_id": thread_id,
                    "success": False,
                    "error": str(e)
                })
        
        # 启动并发连接
        for i in range(concurrent_count):
            thread = threading.Thread(target=connect_test, args=(i,))
            threads.append(thread)
            thread.start()
        
        # 等待所有线程完成
        for thread in threads:
            thread.join()
        
        successful = sum(1 for r in results if r.get("success", False))
        success_rate = (successful / concurrent_count) * 100
        
        self.log_result("并发连接测试", success_rate > 50, {
            "成功连接": f"{successful}/{concurrent_count}",
            "成功率": f"{success_rate:.1f}%",
            "并发数": concurrent_count
        })
    
    def analyze_target_behavior(self):
        """分析目标服务器行为模式"""
        print("🔍 分析目标服务器行为模式...")
        
        connection_intervals = []
        last_success_time = None
        
        for i in range(20):  # 测试20次连接，观察模式
            try:
                sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                sock.settimeout(2)
                
                current_time = time.time()
                result = sock.connect_ex((self.target_ip, self.target_port))
                
                if result == 0:
                    if last_success_time:
                        interval = current_time - last_success_time
                        connection_intervals.append(interval)
                    last_success_time = current_time
                
                sock.close()
                time.sleep(1)
                
            except Exception:
                pass
        
        if connection_intervals:
            avg_interval = sum(connection_intervals) / len(connection_intervals)
            self.log_result("行为模式分析", True, {
                "成功连接间隔": len(connection_intervals),
                "平均间隔": f"{avg_interval:.2f}秒",
                "最短间隔": f"{min(connection_intervals):.2f}秒",
                "最长间隔": f"{max(connection_intervals):.2f}秒",
                "推测": "目标服务器可能每5秒重启监听服务"
            })
        else:
            self.log_result("行为模式分析", False, {
                "问题": "无法建立足够的成功连接来分析模式"
            })
    
    def run_full_diagnostics(self):
        """运行完整诊断"""
        print("=" * 60)
        print("🚀 8888端口连接诊断工具")
        print(f"目标: {self.target_ip}:{self.target_port}")
        print(f"时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
        print("=" * 60)
        print()
        
        # 运行所有测试
        self.test_basic_connectivity()
        self.test_port_accessibility()
        self.test_multiple_connections(10)
        self.test_service_response()
        self.test_concurrent_connections(3)
        self.analyze_target_behavior()
        
        # 生成报告
        self.generate_report()
    
    def generate_report(self):
        """生成诊断报告"""
        print("=" * 60)
        print("📊 诊断报告摘要")
        print("=" * 60)
        
        total_tests = len(self.results["tests"])
        successful_tests = sum(1 for test in self.results["tests"] if test["success"])
        
        print(f"总测试数: {total_tests}")
        print(f"成功测试: {successful_tests}")
        print(f"成功率: {(successful_tests/total_tests)*100:.1f}%")
        print()
        
        # 保存详细报告
        report_file = f"connection_diagnostics_report_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json"
        try:
            with open(report_file, 'w', encoding='utf-8') as f:
                json.dump(self.results, f, indent=2, ensure_ascii=False)
            print(f"详细报告已保存: {report_file}")
        except Exception as e:
            print(f"保存报告失败: {e}")
        
        # 给出建议
        self.provide_recommendations()
    
    def provide_recommendations(self):
        """提供改进建议"""
        print("\n💡 改进建议:")
        print("-" * 40)
        
        # 分析测试结果
        connectivity_test = next((t for t in self.results["tests"] if "连接稳定性" in t["test_name"]), None)
        
        if connectivity_test and connectivity_test["success"]:
            success_rate = float(connectivity_test["details"]["成功率"].replace("%", ""))
            
            if success_rate < 70:
                print("1. 连接成功率较低，建议:")
                print("   - 增加连接重试机制")
                print("   - 调整连接超时时间")
                print("   - 实现智能重连策略")
            
            if success_rate < 50:
                print("2. 连接极不稳定，可能原因:")
                print("   - 目标服务频繁重启")
                print("   - 网络防火墙干扰")
                print("   - 目标服务配置问题")
        
        print("3. 通用建议:")
        print("   - 实现连接状态监控")
        print("   - 添加连接失败日志")
        print("   - 考虑使用备用连接方式")
        print("   - 优化连接时机选择")

def main():
    """主函数"""
    if len(sys.argv) > 1:
        target_ip = sys.argv[1]
    else:
        target_ip = "192.168.10.129"
    
    if len(sys.argv) > 2:
        target_port = int(sys.argv[2])
    else:
        target_port = 8888
    
    diagnostics = ConnectionDiagnostics(target_ip, target_port)
    diagnostics.run_full_diagnostics()

if __name__ == "__main__":
    main()